//+------------------------------------------------------------------+
//|                    DXMesh.mqh DirectX 3D 网格渲染类头文件        |
//|                版权所有 2000-2025, MetaQuotes Ltd.              |
//|                        官方网址: https://www.mql5.com            |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."  // 版权声明
#property link      "https://www.mql5.com"                 // 官方链接

#include "DXObject.h"        // 引入 DirectX 对象基类（提供基础渲染能力）
#include "DXDispatcher.h"    // 引入 DirectX 资源调度器（管理网格依赖资源）
#include "DXData.h"          // 引入 DirectX 数据结构（顶点、矩阵、颜色等）
#include "DXUtils.h"         // 引入 DirectX 工具类（OBJ 模型加载、顶点处理等）

//+------------------------------------------------------------------+
//| CDXMesh 类                                                       |
//| 功能：MT5 DirectX 3D 网格渲染核心类，封装完整的 3D 模型渲染流程   |
//| 继承关系：public CDXObject（基于渲染对象基类，支持基础渲染接口）  |
//| 核心特性：                                                      |
//|  1. 支持两种网格创建方式（顶点/索引数组直接创建、OBJ 模型文件加载）|
//|  2. 集成完整渲染依赖资源（顶点/索引缓冲、着色器、纹理、常量缓冲）  |
//|  3. 支持材质参数配置（漫反射/高光/自发光颜色、高光强度）          |
//|  4. 支持模型变换控制（通过变换矩阵实现平移、旋转、缩放）          |
//|  5. 自动管理资源生命周期（引用计数+统一销毁，避免内存泄漏）        |
//|  6. 适配默认着色器，支持基础光照与纹理渲染                        |
//+------------------------------------------------------------------+
class CDXMesh : public CDXObject
  {
protected:
   //--- DirectX 渲染依赖资源（由资源调度器创建，通过引用计数管理）
   CDXVertexBuffer*  m_buffer_vertex;    // 顶点缓冲区（存储模型顶点数据，如位置、法向量）
   CDXIndexBuffer*   m_buffer_index;     // 索引缓冲区（存储顶点索引，复用顶点数据）
   CDXInput*         m_buffer_object;    // 对象级常量缓冲（传递模型变换、材质参数给着色器）
   CDXInput*         m_buffer_scene;     // 场景级常量缓冲（传递视图、投影、光照参数给着色器）
   CDXShader*        m_shader_vertex;    // 顶点着色器（默认使用内置着色器，处理顶点变换）
   CDXShader*        m_shader_pixel;     // 像素着色器（默认使用内置着色器，处理光照与纹理）
   CDXTexture*       m_texture;          // 纹理资源（模型表面纹理，可选配置）

   //--- 模型核心参数（控制渲染效果与形态）
   DXMatrix          m_transform_matrix; // 模型变换矩阵（包含平移、旋转、缩放，初始为单位矩阵）
   DXColor           m_diffuse_color;    // 漫反射颜色（材质对漫反射光的反射色，默认白色）
   DXColor           m_emission_color;   // 自发光颜色（材质自身发光色，默认黑色，即不发光）
   DXColor           m_specular_color;   // 高光颜色（材质对高光反射的颜色，默认黑色，即无高光）
   float             m_specular_power;   // 高光强度（控制高光区域大小，值越大高光越集中，默认 16.0）

   ENUM_DX_PRIMITIVE_TOPOLOGY m_topology; // 图元拓扑类型（定义顶点如何组成几何体，如三角形列表）

public:
   /**
    * @brief 构造函数：初始化 3D 网格渲染对象
    * @details 调用父类 CDXObject 构造函数，初始化所有资源指针为 NULL，拓扑类型为无效值（WRONG_VALUE）
    */
                     CDXMesh(void);

   /**
    * @brief 析构函数：销毁 3D 网格渲染对象
    * @details 自动调用 Shutdown 方法，释放所有依赖资源（缓冲、着色器、纹理等），避免内存泄漏
    */
                    ~CDXMesh(void);

   //--- 网格创建接口（支持直接创建与文件加载）
   /**
    * @brief 通过顶点和索引数组创建网格（适用于自定义简单模型）
    * @param dispatcher [in] 资源调度器（用于创建顶点/索引缓冲、着色器等依赖资源）
    * @param buffer_scene [in] 场景级常量缓冲（传递视图、投影、光照参数，不可为 NULL）
    * @param vertices [in] 顶点数据数组（DXVertex 类型，存储模型顶点的位置、法向量、纹理坐标、颜色，长度需 ≥1）
    * @param indices [in] 索引数据数组（uint 类型，存储顶点索引，长度需 ≥1，值需在顶点数组范围内）
    * @param topology [in] 图元拓扑类型（默认 DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST，即三角形列表）
    * @return bool - 操作结果：true 表示创建成功（所有依赖资源初始化完成），false 表示失败（如资源创建失败）
    * @note 1. 创建前会自动调用 Shutdown 释放旧资源；2. 初始化默认材质参数（白色漫反射、无自发光/高光）
    */
   bool              Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVertex &vertices[],const uint &indices[],ENUM_DX_PRIMITIVE_TOPOLOGY topology=DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

   /**
    * @brief 通过 OBJ 模型文件创建网格（适用于复杂模型，支持常见 3D 建模软件导出格式）
    * @param dispatcher [in] 资源调度器（用于创建依赖资源）
    * @param buffer_scene [in] 场景级常量缓冲（不可为 NULL）
    * @param obj_path [in] OBJ 文件路径（绝对路径或相对于 MQL5 目录的相对路径）
    * @param scale [in] 模型缩放系数（默认 1.0，大于 1 放大模型，小于 1 缩小模型）
    * @param inverse_winding [in] 绕序反转标志（默认 false，true 用于修正模型正反面渲染错误）
    * @return bool - 操作结果：true 表示创建成功（文件加载+资源初始化完成），false 表示失败（如文件不存在/格式错误）
    * @note 1. 自动将模型顶点颜色设为白色；2. 内部调用 Create(vertices, indices) 完成后续资源创建
    */
   bool              Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,string obj_path,float scale=1.0f,bool inverse_winding=false);

   //--- 网格数据更新接口
   /**
    * @brief 更新网格顶点数据（替换原有顶点缓冲区内容）
    * @param vertices [in] 新顶点数据数组（DXVertex 类型，长度需 ≥1，格式需与原顶点一致）
    * @return bool - 操作结果：true 表示更新成功（顶点数据已同步到 GPU），false 表示失败（如顶点缓冲无效）
    * @note 适用于动态修改模型形态（如变形动画），无需重新创建整个网格
    */
   bool              VerticesSet(const DXVertex &vertices[]);

   /**
    * @brief 更新网格索引数据（替换原有索引缓冲区内容）
    * @param indices [in] 新索引数据数组（uint 类型，长度需 ≥1，值需在当前顶点数组范围内）
    * @return bool - 操作结果：true 表示更新成功（索引数据已同步到 GPU），false 表示失败（如索引缓冲无效）
    * @note 适用于调整模型面的组成方式，需确保索引与顶点数据匹配
    */
   bool              IndicesSet(const uint &indices[]);

   /**
    * @brief 设置网格的图元拓扑类型
    * @param topology [in] 新拓扑类型（如 DX_PRIMITIVE_TOPOLOGY_LINELIST 线列表、DX_PRIMITIVE_TOPOLOGY_POINTLIST 点列表）
    * @return bool - 操作结果：始终返回 true（仅更新拓扑类型变量，无资源操作）
    * @note 需在 Render 前调用，确保渲染时使用正确的拓扑类型解析顶点数据
    */
   bool              TopologySet(ENUM_DX_PRIMITIVE_TOPOLOGY topology);

   //--- 模型变换控制接口（获取/设置变换矩阵）
   /**
    * @brief 获取当前模型的变换矩阵
    * @param mat [out] 变换矩阵（存储当前的平移、旋转、缩放信息）
    * @note 可用于读取模型当前的空间姿态，或基于现有矩阵叠加新变换
    */
   void              TransformMatrixGet(DXMatrix &mat) const;

   /**
    * @brief 设置模型的变换矩阵
    * @param mat [in] 新变换矩阵（通过 DXMatrix 相关函数构建，如 DXMatrixTranslation 平移、DXMatrixRotationY 绕 Y 轴旋转）
    * @note 直接替换原有变换矩阵，适用于精确控制模型的空间姿态（如关键帧动画）
    */
   void              TransformMatrixSet(const DXMatrix &mat);

   //--- 材质参数控制接口（漫反射/高光/自发光）
   /**
    * @brief 获取漫反射颜色
    * @param clr [out] 漫反射颜色（RGBA 格式，每个分量 [0.0,1.0]）
    */
   void              DiffuseColorGet(DXColor &clr) const;

   /**
    * @brief 设置漫反射颜色
    * @param clr [in] 新漫反射颜色（影响模型对环境光和定向光的漫反射效果）
    */
   void              DiffuseColorSet(const DXColor &clr);

   /**
    * @brief 获取高光颜色
    * @param clr [out] 高光颜色（RGBA 格式，通常与光源颜色一致）
    */
   void              SpecularColorGet(DXColor &clr) const;

   /**
    * @brief 设置高光颜色
    * @param clr [in] 新高光颜色（影响模型表面高光反射的颜色，黑色表示无高光）
    */
   void              SpecularColorSet(const DXColor &clr);

   /**
    * @brief 获取高光强度
    * @param power [out] 高光强度（值越大，高光区域越小越集中）
    */
   void              SpecularPowerGet(float &power) const;

   /**
    * @brief 设置高光强度
    * @param power [in] 新高光强度（建议取值范围 1.0~256.0，默认 16.0）
    */
   void              SpecularPowerSet(float power);

   /**
    * @brief 获取自发光颜色
    * @param clr [out] 自发光颜色（RGBA 格式，黑色表示模型不发光）
    */
   void              EmissionColorGet(DXColor &clr) const;

   /**
    * @brief 设置自发光颜色
    * @param clr [in] 新自发光颜色（模型自身发光，不依赖外部光源，适用于光源、特效等）
    */
   void              EmissionColorSet(const DXColor &clr);

   //--- 核心渲染接口
   /**
    * @brief 渲染网格模型（重写父类纯虚方法，实现完整渲染流程）
    * @return bool - 操作结果：true 表示渲染成功（所有资源绑定与绘制完成），false 表示失败（如资源无效）
    * @note 渲染流程：1. 更新对象级常量缓冲（变换矩阵、材质参数）；2. 绑定顶点/索引缓冲、着色器、纹理；3. 设置拓扑类型；4. 执行绘制命令
    */
   virtual bool      Render(void) override;

   //--- 纹理配置接口（为模型添加表面纹理）
   /**
    * @brief 从图片文件为模型设置纹理
    * @param dispatcher [in] 资源调度器（用于创建纹理资源）
    * @param path [in] 图片文件路径（支持 BMP、PNG、JPG 等常见格式）
    * @param data_x [in] 纹理数据起始 X 坐标（默认 0，用于截取图片部分区域作为纹理）
    * @param data_y [in] 纹理数据起始 Y 坐标（默认 0）
    * @param data_width [in] 纹理宽度（默认 0，表示使用图片原始宽度）
    * @param data_height [in] 纹理高度（默认 0，表示使用图片原始高度）
    * @return bool - 操作结果：true 表示纹理设置成功，false 表示失败（如文件不存在/格式不支持）
    * @note 1. 若已有纹理，会先释放旧纹理再创建新纹理；2. 纹理坐标需在顶点数据中正确配置（tcoord 字段）
    */
   bool              TextureSet(CDXDispatcher &dispatcher,string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);

   /**
    * @brief 从原始像素数据为模型设置纹理（适用于动态生成纹理，如实时绘制结果）
    * @param dispatcher [in] 资源调度器（用于创建纹理资源）
    * @param format [in] 纹理像素格式（ENUM_DX_FORMAT，需为 32 位格式，如 DX_FORMAT_R8G8B8A8_UNORM）
    * @param width [in] 纹理宽度（像素，建议为 2 的幂次以优化 GPU 性能）
    * @param height [in] 纹理高度（像素，建议为 2 的幂次）
    * @param data [in] 像素数据数组（uint 类型，每个元素对应一个像素，格式需与 format 匹配）
    * @param data_x [in] 数据起始 X 坐标（默认 0）
    * @param data_y [in] 数据起始 Y 坐标（默认 0）
    * @param data_width [in] 数据宽度（默认 0，表示使用纹理宽度）
    * @param data_height [in] 数据高度（默认 0，表示使用纹理高度）
    * @return bool - 操作结果：true 表示纹理设置成功，false 表示失败（如格式不支持/数据长度不足）
    */
   bool              TextureSet(CDXDispatcher &dispatcher,ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);

   /**
    * @brief 删除模型当前的纹理资源
    * @details 释放纹理资源（调用 Release 减少引用计数），并将纹理指针设为 NULL
    * @note 调用后模型将仅显示材质颜色，不再显示纹理
    */
   void              TextureDelete();

   /**
    * @brief 释放网格所有依赖资源（缓冲、着色器、纹理等）
    * @details 流程：1. 释放顶点/索引缓冲；2. 释放对象/场景级常量缓冲；3. 释放着色器；4. 释放纹理；5. 重置拓扑类型与上下文
    * @note 一般无需手动调用，析构函数会自动触发；可在切换模型时手动调用以释放内存
    */
   virtual void      Shutdown(void);
  };
//+------------------------------------------------------------------+